/*
Copyright (C) 2009-2010 Xanadu Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "Channel.h"
#include "Maps.h"
#include "Players.h"
#include "Player.h"
#include "../tools/PacketCreator.h"
#include "../tools/Timer.h"
#include "../tools/Run.h"
#include "../tools/Tools.h"
#include "Transportations.h"
#include "Map.h"
#include "../net/world/Party.h"
#include "../net/world/Worlds.h"
#include "../scripting/AngelScriptEngine.h"
#include "../client/EventsData.h"
#include "../client/EventData.h"
#include "Events.h"
#include "Event.h"
#include "../client/ChannelEventsData.h"
#include "../client/ChannelEventData.h"

using namespace Tools;

class ChannelEventTimer : public Run {
private:
	Channel* channel;
public:
	ChannelEventTimer(Channel* channel): channel(channel) {}
	void run(){
		int time = getMinute();
		vector <ChannelEventData*>* events = ChannelEventsData::getInstance()->getData();
		for(int i=0; i<(int)events->size(); i++){
			ChannelEventData* eventd = (*events)[i];
			if(eventd->getTime() > 0 && (time-eventd->getFirst())%eventd->getTime() == 0){
				AngelScriptEngine::handleChannelEvent(channel, eventd->getName());
			}
		}	
		Timers::getInstance()->startTimer(getTimeUntilNextMinute(), new ChannelEventTimer(channel));
	}
};

void Channel::channelEventTimer(){
	int time = Tools::getMinute();
	std::vector <ChannelEventData*> *events = ChannelEventsData::getInstance()->getData();
	for(int i = 0; i< (int)events->size(); i++){
		ChannelEventData* eventd = (*events)[i];
		if(eventd->getTime() > 0 && (time-eventd->getFirst())%eventd->getTime() == 0) 
			AngelScriptEngine::handleChannelEvent(this, eventd->getName());
	}
}
Channel::Channel(World* world, int id, int port)/* : timers(new Timer::Container)*/ {
	this->world = world;
	this->id = id;
	maps = new Maps(this);
	players = new Players();
	trans = new Transportations();
	events = new Events(this);
	Event::id = 0;
	header = Worlds::getInstance()->getDefaultHeader();
	this->port = port;
	Timers::getInstance()->startTimer(getTimeUntilNextMinute(), new ChannelEventTimer(this));	
}

void Channel::addPlayer(Player* player) {
	players->add(player);
	player->getMap()->addPlayer(player);
	player->send(PacketCreator().showMessage(header, 4, 0, true));
}

Map* Channel::getMap(int id) {
	return maps->getMap(id);
}

bool Channel::createEventForPlayer(std::string& name, Player* player) {
	EventData* eventd = EventsData::getInstance()->getDataByID(name);
	if(eventd == 0)
		return false;
	if(isEventActive(name))
		return false;
	if(!events->createEvent(name))
		return false;
	events->addPlayer(name, player);
	return true;
}

bool Channel::createEventForPlayers(std::string& name, Players* players) {
	EventData* eventd = EventsData::getInstance()->getDataByID(name);
	if(eventd == NULL)
		return false;
	if(isEventActive(name))
		return false;
	if(!events->createEvent(name))
		return false;
	struct AddToEvent {
		void operator()(Player* player) {
			events->addPlayer(name, player);
		}
		Events* events;
		string name;
	}
	addToEvent = {
		events, name
	};
	players->run(&addToEvent);
	return true;
}

bool Channel::createEventForParty(std::string& name, Party* party) {
	bool ret = createEventForPlayers(name, (Players*)party->getMembers());
	if(ret && events->getEvent(name) != NULL) {
		events->getEvent(name)->setParty(party);
	}
	return ret;
}

bool Channel::createEvent(std::string& name) {
	EventData* eventd = EventsData::getInstance()->getDataByID(name);
	if(eventd == NULL)
		return false;
	if(isEventActive(name)) 
		return false;
	if(!events->createEvent(name)) 
		return false;
	return true;
}

void Channel::deleteEvent(std::string& name) {
	events->deleteEvent(name);
}

void Channel::deleteEventForPlayer(std::string& name, Player* player) {
	events->deleteEventForPlayer(name, player);
}

bool Channel::isEventActive(string& name) {
	return events->isEventActive(name);
}